/*
 *	ME2 C++ SDK
 *	Copyright (c) 2010 _silencer
 *
 *	Permission is hereby granted, free of charge, to any person
 *	obtaining a copy of this software and associated documentation
 *	files (the "Software"), to deal in the Software without
 *	restriction, including without limitation the rights to use,
 *	copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the
 *	Software is furnished to do so, subject to the following
 *	conditions:
 *
 *	The above copyright notice and this permission notice shall be
 *	included in all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *	OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef UNREAL_CHECK_H
#define UNREAL_CHECK_H

#include "unreal_sdk.h"

namespace unreal
{
	class ucheck
	{
	public:

		virtual ~ucheck(){}
		virtual bool conforms(){ return false; }
	};

	#define DECLARE_CHECK_CLASS( type ) \
	class check_##type: public ucheck \
	{ \
	public: \
		typedef type checked_type; \
		check_##type() \
			:  static_class_( type::static_get_class() )\
		{ \
			if ( static_class_->is_valid() ) \
				size_ = static_class_->get_properties_size(); \
			else \
				size_ = 0; \
		} \
		bool conforms() \
		{ \
			return sizeof(type) == size_; \
		} \
		uint32 get_conforming_size() \
		{ \
			return size_; \
		} \
	private: \
		uclass* static_class_; \
		uint32 size_; \
	};

	#define IMPLEMENT_CHECK_CLASS( type ) \
	{ \
		unreal::check_##type check_##type##_instance; \
		if ( check_##type##_instance.conforms() ) \
			std::cout << "Information " << #type << " does conform with engine definition ( " << sizeof(unreal::type) << " == " << check_##type##_instance.get_conforming_size() << " )!" << std::endl; \
		else \
			std::cout << "Warning " << #type << " does not conform with engine definition ( " << sizeof(unreal::type) << " != " << check_##type##_instance.get_conforming_size() << " )!" << std::endl; \
	}

	DECLARE_CHECK_CLASS( uobject )
		DECLARE_CHECK_CLASS( ucomponent )
		DECLARE_CHECK_CLASS( utextbuffer )
		DECLARE_CHECK_CLASS( ufield )
			DECLARE_CHECK_CLASS( uenum )
			DECLARE_CHECK_CLASS( uconst )
			DECLARE_CHECK_CLASS( uproperty )
				DECLARE_CHECK_CLASS( ubyteproperty )
				DECLARE_CHECK_CLASS( uintproperty )
				DECLARE_CHECK_CLASS( uboolproperty )
				DECLARE_CHECK_CLASS( ufloatproperty )
				DECLARE_CHECK_CLASS( uobjectproperty )
					DECLARE_CHECK_CLASS( uclassproperty )
					DECLARE_CHECK_CLASS( ucomponentproperty )
				DECLARE_CHECK_CLASS( unameproperty )
				DECLARE_CHECK_CLASS( ustructproperty )
				DECLARE_CHECK_CLASS( ustrproperty )
				DECLARE_CHECK_CLASS( uarrayproperty )
				DECLARE_CHECK_CLASS( umapproperty )
				DECLARE_CHECK_CLASS( uinterfaceproperty )
				DECLARE_CHECK_CLASS( udelegateproperty )
				DECLARE_CHECK_CLASS( ustringrefproperty )
			DECLARE_CHECK_CLASS( ustruct )
				DECLARE_CHECK_CLASS( ufunction )
				DECLARE_CHECK_CLASS( ustate )
					DECLARE_CHECK_CLASS( uclass )
}

#endif
